package com.aote.component.block;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.browsesoft.ExtendElement;
import com.browsesoft.Tools;
import com.browsesoft.htmlcomponent.HTMLBasicComponent;
import com.browsesoft.htmlcomponent.HTMLTableModel;

/**
 * 数据块组件
 * 
 */
public class HTMLDatasBlockComponent extends HTMLBasicComponent {
	/**
	 * 表格块头组件
	 */
	private HTMLBasicComponent blockHeadComponent = null;

	/**
	 * 表格块左侧组件
	 */
	private HTMLBasicComponent blockLeftComponent = null;

	/**
	 * 表格块组件
	 */
	private HTMLBasicComponent tableBlockComponent = null;

	private Element srcElement = null;

	public HTMLDatasBlockComponent(HTMLBasicComponent parent) throws Exception {
		super(parent);
	}

	/**
	 * 初始化时创建子组件并设置初始化参数
	 */
	public void init(HttpServletRequest request, Element e) throws Exception {
		super.init(request, e);
		this.srcElement = (Element) this.getElement().cloneNode(true);
	}

	/**
	 * 设置表格块头组件
	 */
	public void setBlockHeadComponent(HTMLBasicComponent component) {
		this.blockHeadComponent = component;
	}

	/**
	 * 设置表格左侧组件
	 */
	public void setBlockLeftComponent(HTMLBasicComponent component) {
		this.blockLeftComponent = component;
	}

	/**
	 * 设置表格块组件
	 */
	public void setTableBlockComponent(HTMLBasicComponent component) {
		this.tableBlockComponent = component;
	}

	/**
	 * 得到表格块组件
	 */
	public HTMLBasicComponent getTableBlockComponent() {
		return this.tableBlockComponent;
	}

	protected void updateElement() throws Exception {
		super.updateElement();
		this.crateDataElements();
	}

	/**
	 * 创建数据元素
	 * 
	 */
	protected void crateDataElements() {
		// 得到页面表体所有tr行，创建数据元素
		NodeList trs = this.getElement().getElementsByTagName("tr");
		// 左侧表体块参数计数
		int leftIndex = 0;
		String leftParam = "";
		for (int i = 0; i < trs.getLength(); i++) {
			Element tr = (Element) trs.item(i);
			// 如果tr中有type="datatr"标记说明是一个数据块行的开始，得到数据参数
			if (isDataTrStart(tr)) {
				leftParam = getLeftParam(leftIndex);
				leftIndex++;
			}
			// 复制数据元素，并替换条件参数
			createDataElemnts(tr, leftParam, i);
		}
	}

	/**
	 * 判断该行是否是一个数据块的开始行
	 */
	protected boolean isDataTrStart(Element trElem) {
		String type = trElem.getAttribute("type");
		if (type != null && type.equals("datatr")) {
			return true;
		}
		return false;
	}

	/**
	 * 得到左侧表体参数
	 */
	protected String getLeftParam(int index) {
		return ((HTMLTableModel) this.blockLeftComponent.getModel())
				.getColumnName(index);
	}

	/**
	 * 创建数据元素
	 */
	protected void createDataElemnts(Element trElem, String leftParam, int row) {
		// 从表头块组件得到列数,如果cols等于－1，说明没有表头
		int cols = this.getHeadCols();
		// 无表头处理
		if (cols == -1) {
			createSingleRowElements(trElem, leftParam, row);
		}
		// 有表头，根据表头列数进行元素创建
		else {
			createSingleRowElements(trElem, leftParam, row, cols);
		}
	}

	private void createSingleRowElements(Element trElem, String leftParam,
			int row, int cols) {
		// 如果是总合计行type="allsum",特殊处理，重新从缓存的模板元素取得tr
		if (trElem.getAttribute("type").equals("allsum")) {
			Element tempTrElem = getSrcAllSumTr();
			Node parent = trElem.getParentNode();
			parent.removeChild(trElem);
			trElem = (Element) this.getPage().getElement().getOwnerDocument()
					.importNode(tempTrElem, true);
			parent.appendChild(trElem);
		}
		// 根据现在页面trElem中的类型得到模版中的数据元素
		Element dataElem = (Element) trElem
				.getElementsByTagName("datatemplate").item(0);
		Collection tds = ExtendElement.getChildrenCopy(dataElem);
		ExtendElement.removeChilds(dataElem);
		for (int i = 0; i < cols; i++) {
			// 得到表头列参数
			String headParam = getHeadParam(i);
			// 复制数据部分
			Collection newTds = ExtendElement.getCopy(tds);
			// 创建单行元素
			createSingleRowElements(newTds, leftParam, headParam, row, i);
			ExtendElement.append(dataElem, newTds);
		}
		// copytemplate中的内容不动，直接计算
		int col = cols * tds.size();
		this.processCopyTemplate(trElem, row, col);
	}

	private Element getSrcAllSumTr() {
		Element result = (Element) ExtendElement.findElements(this.srcElement,
				"type", "allsum").get(0);
		return (Element) result.cloneNode(true);
	}

	/**
	 * 处理copytemplate里的内容
	 */
	private void processCopyTemplate(Element trElem, int row, int col) {
		NodeList nl = trElem.getElementsByTagName("datacopytemplate");
		// 如果没有copytemplate，不处理
		if (nl.getLength() == 0) {
			return;
		}
		// 对应copytempalte中的每一个td
		Element ct = (Element) nl.item(0);
		NodeList tds = ct.getElementsByTagName("td");
		int len = tds.getLength();
		HTMLTableModel m = (HTMLTableModel) model;
		Document doc = this.getPage().getDocument();
		for (int i = 0; i < len; i++) {
			Element td = (Element) tds.item(i);
			// 设置td名称,名称为 nRownCol
			int colNum = col + i;
			String name = row + "row" + colNum + "col";
			td.setAttribute("name", name);
			// 让模型处理
			m.modifyCellValue(td, doc, row, colNum);
		}
	}

	/**
	 * 创建单行元素
	 */
	protected void createSingleRowElements(Collection tds, String leftParam,
			String headParam, int row, int col) {
		int len = tds.size();
		Iterator iter = tds.iterator();
		for (int i = 0; iter.hasNext(); i++) {
			Element tdElem = (Element) iter.next();
			// 替换条件
			replaceTdCondition(tdElem, leftParam, headParam);
			// 设置td名称,名称为 nRownCol
			int colNum = col * len + i;
			String name = row + "row" + colNum + "col";
			tdElem.setAttribute("name", name);
			// 由model更改数据显示
			((HTMLTableModel) model).modifyCellValue(tdElem, this.getPage()
					.getDocument(), row, colNum);
		}
	}

	private void setNameForChildElem(Element tdElem, String name) {
		if (tdElem.getFirstChild() instanceof Element) {
			Element elem = (Element) tdElem.getChildNodes();
			elem.setAttribute("name", name);
		}
	}

	/**
	 * 创建单行元素
	 */
	protected void createSingleRowElements(Element trElem, String leftParam,
			int row) {
		// 根据现在页面trElem中的类型得到模版中的数据元素
		Element dataElem = (Element) trElem
				.getElementsByTagName("datatemplate").item(0);
		NodeList list = dataElem.getElementsByTagName("td");
		for (int i = 0; i < list.getLength(); i++) {
			Element tdElem = (Element) list.item(i);
			// 替换条件
			replaceTdCondition(tdElem, leftParam, null);
			// 设置td名称,名称为 nRownCol
			String name = row + "row" + i + "col";
			tdElem.setAttribute("name", name);
			// 如果td下有元素，给元素设置名字
			setNameForChildElem(tdElem, name);
			// 由model更改数据显示
			((HTMLTableModel) model).modifyCellValue(tdElem, this.getPage()
					.getDocument(), row, i);
		}
	}

	/**
	 * 得到列数
	 */
	protected int getCols(int headCols, int col) {
		if (headCols == -1) {
			return col;
		} else {
			return headCols + col;
		}
	}

	/**
	 * 得到表头列数
	 */
	protected int getHeadCols() {
		if (this.blockHeadComponent == null) {
			return -1;
		} else {
			return ((HTMLTableModel) this.blockHeadComponent.getModel())
					.getColumnCount();
		}
	}

	/**
	 * 得到表头参数
	 */
	protected String getHeadParam(int index) {
		return ((HTMLTableModel) this.blockHeadComponent.getModel())
				.getColumnName(index);
	}

	/**
	 * 替换td中的表头和左侧标题参数
	 */
	protected void replaceTdCondition(Element td, String leftParam,
			String headParam) {
		String condition = td.getAttribute("condition");
		condition = condition.replaceAll("#leftparam#", leftParam);
		condition = replaceHeadCondition(headParam, condition);
		td.setAttribute("condition", condition);
	}

	/**
	 * 替换表头
	 * 
	 * @param headParam
	 * @param condition
	 * @return
	 */
	private String replaceHeadCondition(String headParam, String condition) {
		String result = condition;
		List l = Tools.stringToLinkedList(headParam);
		// 如果是单层表头，替换内容
		if (l.size() == 1) {
			result = result.replaceAll("#headparam#", headParam);
			return result;
		}
		// 多层表头，参数是以逗号分割的各层的值
		for (int i = 0; i < l.size(); i++) {
			String param = (String) l.get(i);
			// 替换第i层的值
			result = result.replaceAll("#headparam" + (i + 1) + "#", param);
		}
		return result;
	}
}
